<?php

namespace app\common\model;

/*
 * 抖音店铺团购券核销
 * author: kai
 *
 */

class Douyin
{
    protected $Appid = '';
    protected $AppSecret = '';
    protected $pro_id = ''; // 门店id

    public function __construct($Appid, $AppSecret, $pro_id = '')
    {
        $this->Appid = $Appid;
        $this->AppSecret = $AppSecret;
        $this->pro_id = $pro_id;
    }

    /*
     *  这里是核销的方法
     */
    public function run($encrypted_data, $code = null)
    {
        $encrypted_data = '100000000000000';   // code  格式 100000000000000
        $client_token = $this->get_client_token();
        if (!$client_token) {
            die('token 获取失败');
        }
        $res = $this->prepareCertificate($client_token, '', $encrypted_data);
        $v = $res['data']['verify_token'];
        $code = $res['data']['certificates'][0]['encrypted_code'];
        $hexiao = $this->verifyCoupon($v, $client_token, $this->pro_id, [$code]);
        //核销之后的所有信息都在这里 打印自己看就行
        print_r($hexiao);
    }

    /**
     * @param $access_token
     * @param $encrypted_data
     * @param null $code
     * @return mixed
     * 通过code 核销券码准备
     */
    public function prepareCertificate($access_token, $encrypted_data, $code = null)
    {
        $url = 'https://open.douyin.com/goodlife/v1/fulfilment/certificate/prepare/';

        $params = [];
        if (!empty($encrypted_data)) {
            $params['encrypted_data'] = urlencode($this->shortenToLong($encrypted_data));
        } elseif (!empty($code)) {
            $params['code'] = $code;
        } else {
            throw new \Exception("encrypted_data 和 code 参数不能同时为空");
        }
        $back = $this->k_request($url, $params, $access_token, 0);
        return $back;
    }

    /**
     * 核销券
     * @param $verifyToken
     * @param $client_token
     * @param $poiId
     * @param $encryptedCodes
     * @param null $codes
     * @param null $orderId
     * @param null $codeWithTimeList
     * @param null $voucher
     * @return mixed
     */
    public function verifyCoupon($verifyToken, $client_token, $poiId, $encryptedCodes, $codes = null, $orderId = null, $codeWithTimeList = null, $voucher = null)
    {
        $url = 'https://open.douyin.com/goodlife/v1/fulfilment/certificate/verify/';
        $data = array(
            'verify_token' => $verifyToken,
            'poi_id' => $poiId,
            'encrypted_codes' => $encryptedCodes,
            'codes' => $codes,
        );

        $response = $this->k_request($url, $data, $client_token);
        return $response;
    }


    /**
     * 撤销券
     * verify_id 代表券码一次核销的唯一标识（验券时返回）(次卡撤销多次时请填0)
     * certificate_id 代表一张券码的标识（验券时返回）
     * @return mixed
     */
    public function revokeCoupon($verify_id, $certificate_id, $client_token)
    {
        $url = 'https://open.douyin.com/goodlife/v1/fulfilment/certificate/cancel/';
        $data = array(
            'verify_id' => $verify_id,
            'certificate_id' => $certificate_id,
        );

        $response = $this->k_request($url, $data, $client_token);
        return $response;
    }

    /**
     * @return mixed
     * 获取token
     */
    public function get_client_token()
    {
        //正式环境：https://open.douyin.com/oauth/client_token/
        //沙盒环境：https://open-sandbox.douyin.com/oauth/client_token/
        $url = 'https://open.douyin.com/oauth/client_token/';
        $param = [
            'client_key' => $this->Appid,
            'client_secret' => $this->AppSecret,
            'grant_type' => 'client_credential'
        ];

        $res = $this->request($url, $param);
        $back = json_decode($res, true);
        if ($back['data']['error_code'] == 0) {
            return $back['data']['access_token'];
        }

    }

    //curl 提交
    public function request($url, $data = null, $https = true, $method = 'post')
    {
        //1.初始化url
        $ch = curl_init($url);
        //2.设置相关的参数
        //字符串不直接输出,进行一个变量的存储
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //判断是否为https请求
        if ($https === true) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        //判断是否为post请求
        if ($method == 'post') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:multipart/form-data'));
        //3.发送请求
        $str = curl_exec($ch);
        //4.关闭连接
        curl_close($ch);
        //6.返回请求到的结果
        return $str;
    }


    /**
     * 抖音请求方法
     * @param $url
     * @param $client_token
     * @param array $data
     * @param int $is_post
     * @return mixed
     */
    public function k_request($url, $data = [], $client_token = '', $is_post = 1)
    {
        $headers = [
            'Content-Type: application/json',
            'access-token: ' . $client_token,
        ];
        $curl = curl_init();
        if ($is_post) {
            curl_setopt_array($curl, array(
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => json_encode($data),
                CURLOPT_HTTPHEADER => $headers,
            ));
        } else {
            $data = http_build_query($data);
            curl_setopt_array($curl, [
                CURLOPT_URL => "$url?$data",
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTPHEADER => $headers,
            ]);
        }
        $response = curl_exec($curl);
        curl_close($curl);
        return json_decode($response, true);
    }

    public function shortenToLong($short_url)
    {
        // 初始化cURL资源
        $ch = curl_init($short_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回字符串
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'); // 模拟浏览器UserAgent
        curl_setopt($ch, CURLOPT_HEADER, true); // 允许获取响应头信息

        // 执行cURL请求，获取响应数据
        $response = curl_exec($ch);

        // 检查响应状态码，如果是301或302（表示重定向），则从响应头信息中提取出目标地址
        $http_code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        if ($http_code == 301 || $http_code == 302) {
            $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
            $header = substr($response, 0, $header_size);
            $body = substr($response, $header_size);

            // 从响应头信息中提取出目标地址（Location字段）
            preg_match('/Location: (.*?)\n/', $header, $matches);
            if (isset($matches[1])) {
                $long_url = trim($matches[1]); // 去除前后空格和换行符
            } else {
                return ""; // 如果没有找到Location字段，返回错误信息 无法获取长链接
            }
        } else {
            return ""; // 如果不是301或302状态码，返回错误信息 短链接无效
        }
        // 将目标地址与预先定义的HTML标签拼接，形成完整的长链接。这里我们使用<a>标签进行拼接。
        return $this->extract_name_from_url($long_url); // 返回长链接。你可以根据需要修改这个返回值。例如，你可以将长链接存储在数据库或文件中。
    }

    public function extract_name_from_url($url) {
        // 定义正则表达式，用于匹配URL中的name变量。例如：http://example.com/?name=John%20Doe&age=30。这个正则表达式会匹配到name=John%20Doe。
        $pattern = '/object_id=([^&]+)/';

        // 使用preg_match()函数进行匹配，如果匹配成功，将返回匹配的结果。如果没有找到匹配的结果，preg_match()将返回0。
        if (preg_match($pattern, $url, $matches)) {
            return urldecode($matches[1]); // 使用urldecode()函数对提取到的name变量进行解码，以得到原始的字符串。
        } else {
            return ""; // 如果没有找到匹配的结果，返回错误信息。
        }
    }
}